home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / srcuc.zip / CMPGC.H < prev    next >
C/C++ Source or Header  |  1992-03-09  |  14KB  |  423 lines

  1. /* -*-C-*-
  2.  
  3. $Header: /scheme/src/microcode/RCS/cmpgc.h,v 1.19 1992/03/10 02:54:02 jinx Exp $
  4.  
  5. Copyright (c) 1989-1992 Massachusetts Institute of Technology
  6.  
  7. This material was developed by the Scheme project at the Massachusetts
  8. Institute of Technology, Department of Electrical Engineering and
  9. Computer Science.  Permission to copy this software, to redistribute
  10. it, and to use it for any purpose is granted, subject to the following
  11. restrictions and understandings.
  12.  
  13. 1. Any copy made of this software must include this copyright notice
  14. in full.
  15.  
  16. 2. Users of this software agree to make their best efforts (a) to
  17. return to the MIT Scheme project any improvements or extensions that
  18. they make, so that these may be included in future releases; and (b)
  19. to inform MIT of noteworthy uses of this software.
  20.  
  21. 3. All materials developed as a consequence of the use of this
  22. software shall duly acknowledge such use, in accordance with the usual
  23. standards of acknowledging credit in academic research.
  24.  
  25. 4. MIT has made no warrantee or representation that the operation of
  26. this software will be error-free, and MIT is under no obligation to
  27. provide any services, by way of maintenance, update, or otherwise.
  28.  
  29. 5. In conjunction with products arising from the use of this material,
  30. there shall be no use of the name of the Massachusetts Institute of
  31. Technology nor of any adaptation thereof in any advertising,
  32. promotional, or sales literature without prior written consent from
  33. MIT in each case. */
  34.  
  35. /*
  36.  
  37. Utilities to relocate compiled code in garbage collection-like processes. 
  38.  
  39. This file is included by gccode.h.
  40.  
  41. See cmpint.txt, cmpint.c, cmpint-md.h, and cmpaux-md.m4 for more details.
  42. */
  43.  
  44. #ifndef CMPGC_H_INCLUDED
  45. #define CMPGC_H_INCLUDED
  46.  
  47. #define NOP() do {} while (0) /* A useful macro */
  48.  
  49. /* These are needed whether or not there is a compiler,
  50.    so their definition must be outside the HAS_COMPILER_SUPPORT ifdef.
  51.  */
  52.  
  53. #define OPERATOR_LINKAGE_KIND            0x000000
  54. #define REFERENCE_LINKAGE_KIND            0x010000
  55. #define ASSIGNMENT_LINKAGE_KIND            0x020000
  56. #define GLOBAL_OPERATOR_LINKAGE_KIND        0x030000
  57.  
  58. #ifdef HAS_COMPILER_SUPPORT
  59.  
  60. #include "cmpint2.h"
  61.  
  62. /*
  63.   The following is a kludge which is used to get return_to_interpreter
  64.   to work.  The return to interpreter block is never dumped on normal
  65.   bin files, but is dumped in complete bands.  As long as it does not
  66.   change in position with respect to the beginning of constant space,
  67.   it will be relocated correctly on reload.
  68. */
  69.  
  70. #ifndef In_Fasdump
  71.  
  72. #define COMPILED_CODE_PRE_TEST(then_what)
  73.  
  74. #else
  75.  
  76. extern SCHEME_OBJECT compiler_utilities;
  77.  
  78. #define COMPILED_CODE_PRE_TEST(then_what)                \
  79. if (Old == (OBJECT_ADDRESS (compiler_utilities)))            \
  80.   then_what;                                \
  81. else
  82.  
  83. #endif
  84.  
  85. /*
  86.    The following code handles compiled entry points, where the
  87.    addresses point to the "middle" of the code vector.  From the entry
  88.    address, the offset word can be extracted, and this offset allows
  89.    us to find the beginning of the block, so it can be copied as a
  90.    whole.  The broken heart for the whole block lives in its usual
  91.    place (first word in the vector).
  92.  
  93.    The offset word contains an encoding of the offset and an encoding
  94.    of whether the resulting pointer points to the beginning of the
  95.    block or is another entry, so the process may have to be repeated.
  96.  
  97.    Pointers to char are used here because compiled entry points do not
  98.    in general point to Pointer boundaries.
  99.  */
  100.  
  101. #define Get_Compiled_Block(var, address)                \
  102. {                                    \
  103.   long offset_word;                            \
  104.                                     \
  105.   var = (address);                            \
  106.                                     \
  107.   do                                    \
  108.   {                                    \
  109.     offset_word = (COMPILED_ENTRY_OFFSET_WORD(var));            \
  110.     var = ((SCHEME_OBJECT *)                        \
  111.        (((char *) (var)) -                        \
  112.         (OFFSET_WORD_TO_BYTE_OFFSET(offset_word))));        \
  113.   } while (OFFSET_WORD_CONTINUATION_P(offset_word));            \
  114. }
  115.  
  116. #define RELOCATE_COMPILED_ADDRESS(object, new_block, old_block)        \
  117. ((SCHEME_OBJECT *) (((char *) new_block) +                \
  118.             (((char *) (OBJECT_ADDRESS(object))) -        \
  119.              ((char *) old_block))))
  120.  
  121. #define RELOCATE_COMPILED(object, new_block, old_block)            \
  122. MAKE_POINTER_OBJECT((OBJECT_TYPE(object)),                \
  123.             (RELOCATE_COMPILED_ADDRESS(object, new_block, old_block)))
  124.  
  125. #define Compiled_BH(In_GC, then_what)                    \
  126. {                                    \
  127.   /* Has it already been relocated? */                    \
  128.                                     \
  129.   Get_Compiled_Block (Old, Old);                    \
  130.   COMPILED_CODE_PRE_TEST (then_what)                    \
  131.   if (BROKEN_HEART_P (*Old))                        \
  132.   {                                    \
  133.     Temp = (RELOCATE_COMPILED (Temp, (OBJECT_ADDRESS (*Old)), Old));    \
  134.     then_what;                                \
  135.   }                                    \
  136. }
  137.  
  138. #define Transport_Compiled()                        \
  139. {                                    \
  140.   SCHEME_OBJECT *Saved_Old = Old;                    \
  141.                                     \
  142.   Real_Transport_Vector();                        \
  143.   *Saved_Old = New_Address;                        \
  144.   Temp = (RELOCATE_COMPILED (Temp,                    \
  145.                  (OBJECT_ADDRESS (New_Address)),        \
  146.                  Saved_Old));                \
  147. }
  148.  
  149. /* Manifest and implied types */
  150.  
  151. /* Manifest closures */
  152.  
  153. /* A manifest closure header is followed by one or more closure entry
  154.    points.  Each entry point consist of a pair of machine words (16
  155.    bits each) that contain a format word and a GC offset followed by
  156.    the machine code for the closure (typically a jsr-type
  157.    instruction).  If there is only one entry point to a closure, the
  158.    GC offset will be 8 bytes, pointing back to the manifest closure
  159.    header itself.  Otherwise what would have been the first GC offset
  160.    is 0, and what would have been the first format word is the count
  161.    in entry points.  The format word and GC offset for the first entry
  162.    follow this additional word.  After the entry points there are the
  163.    values of the variables closed over:
  164.  
  165.           >=1 Entry Point          =1 Entry Point
  166.    (offset in bytes from 1st instruction of 1st (only) entry)
  167.  
  168.      -12: Manifest Closure | tot. length
  169.      - 8: Count format word (with 0 GC)  Manifest Closure | tot. length
  170.         : optional padding
  171.      - 4: Format word, 1st entry         Format word, only entry
  172.      - 2: GC offset to -12               GC offset to -8
  173.        0: jsr instr., 1st entry         jsr instr.
  174.       xx: more instructions if needed    same
  175.         : Format word, 2nd entry         closed over variable values
  176.         : GC offset to -16
  177.      ...: etc.
  178.      ...: closed over variable values
  179.  
  180.    FIRST_MANIFEST_CLOSURE_ENTRY receives the address of the word past
  181.    the manifest closure header (-4 for single entry point closures in
  182.    the above picture).  It bumps it to the first entry point (i.e. to
  183.    0 above), past the format word and the gc offset and the count
  184.    formart word if present.
  185.  
  186.    MANIFEST_CLOSURE_COUNT receives the address of the word past the
  187.    manifest closure header and extracts the count of entry points
  188.    in the closure block.
  189.  
  190.    CLOSURE_HEADER_TO_ENTRY is the distance (in bytes) from the
  191.    manifest closure header to the 1st instruction of the (1st) entry.
  192.  */
  193.  
  194. #ifndef MULTI_CLOSURE_PADDING
  195. #   define MULTI_CLOSURE_PADDING     0 /* Bytes! */
  196. #endif
  197.  
  198. #define CLOSURE_HEADER_TO_ENTRY                        \
  199. ((sizeof (SCHEME_OBJECT)) + (2 * (sizeof (format_word))))
  200.  
  201. #define CLOSURE_HEADER_TO_ENTRY_WORD                    \
  202. ((format_word) (BYTE_OFFSET_TO_OFFSET_WORD (CLOSURE_HEADER_TO_ENTRY)))
  203.  
  204. #define MANIFEST_CLOSURE_COUNT(scan)                    \
  205. (((((format_word *) (scan))[1]) ==                    \
  206.   CLOSURE_HEADER_TO_ENTRY_WORD) ?                    \
  207.  1 :                                    \
  208.  ((long) (((format_word *) (scan))[0])))
  209.  
  210. #define FIRST_MANIFEST_CLOSURE_ENTRY(scan)                \
  211. (((((format_word *) (scan))[1]) == CLOSURE_HEADER_TO_ENTRY_WORD) ?    \
  212.  (((char *) (scan)) + (2 * (sizeof (format_word)))) :            \
  213.  (((char *) (scan))                            \
  214.   + (MULTI_CLOSURE_PADDING + (4 * (sizeof (format_word))))))        \
  215.  
  216. #define NEXT_MANIFEST_CLOSURE_ENTRY(word_ptr)                \
  217.   (((char *) (word_ptr)) + (COMPILED_CLOSURE_ENTRY_SIZE))
  218.  
  219. /* Where this closure entry ends with respect to the entry point.
  220.    Since an entry point is preceded by a format word and a gc offset,
  221.    it is the address of the next entry minus these two words.
  222.  */
  223.  
  224. #define CLOSURE_ENTRY_END(word_ptr)                    \
  225.   (((char *) (word_ptr)) +                        \
  226.    ((COMPILED_CLOSURE_ENTRY_SIZE) - (2 * (sizeof (format_word)))))
  227.  
  228. #define CHAR_TO_SCHEME_OBJECT(chars)                    \
  229. (((chars) + ((sizeof (SCHEME_OBJECT)) - 1)) / (sizeof (SCHEME_OBJECT)))
  230.  
  231. /* This takes into account the fact that the relocation loop increments
  232.    by 1 on each major iteration.
  233.    Note: It also assumes that closures with exactly one entry point
  234.    are always represented in short format.
  235.  */
  236.  
  237. #define MANIFEST_CLOSURE_END(start, count)                \
  238. (((SCHEME_OBJECT *) (start))                        \
  239.  + ((CHAR_TO_SCHEME_OBJECT (((count) * COMPILED_CLOSURE_ENTRY_SIZE)    \
  240.                 + (((count) == 1)                \
  241.                    ? 0                    \
  242.                    : (MULTI_CLOSURE_PADDING            \
  243.                   + (2 * sizeof(format_word))))))    \
  244.     - 1))                                \
  245.  
  246. /* Linkage sections */
  247.  
  248. #define READ_LINKAGE_KIND(header)                    \
  249.   ((header) & 0xff0000)
  250.  
  251. #define READ_CACHE_LINKAGE_COUNT(header)                \
  252.   ((header) & 0xffff)
  253.  
  254. #ifndef FIRST_OPERATOR_LINKAGE_OFFSET
  255. #  define FIRST_OPERATOR_LINKAGE_OFFSET 1
  256. #endif
  257.  
  258. #define READ_OPERATOR_LINKAGE_COUNT(header)                \
  259.   (EXECUTE_CACHE_COUNT_TO_ENTRIES                    \
  260.    (((header) & 0xffff) - (FIRST_OPERATOR_LINKAGE_OFFSET - 1)))
  261.   
  262. #define MAKE_LINKAGE_SECTION_HEADER(kind, count)            \
  263.   (MAKE_OBJECT(TC_LINKAGE_SECTION,                    \
  264.            ((kind)                            \
  265.         | ((((kind) == OPERATOR_LINKAGE_KIND)            \
  266.             || ((kind) == GLOBAL_OPERATOR_LINKAGE_KIND))    \
  267.            ? ((EXECUTE_CACHE_ENTRIES_TO_COUNT (count))        \
  268.               + (FIRST_OPERATOR_LINKAGE_OFFSET - 1))        \
  269.            : (count)))))
  270.  
  271. /* This takes into account the 1 added by the main loop of the
  272.    relocators.
  273.  */
  274.  
  275. #ifndef END_OPERATOR_LINKAGE_AREA
  276. #  define END_OPERATOR_LINKAGE_AREA(scan, count)            \
  277.   (((SCHEME_OBJECT *) (scan))                        \
  278.    + (((count) * EXECUTE_CACHE_ENTRY_SIZE))                \
  279.    + (FIRST_OPERATOR_LINKAGE_OFFSET - 1))
  280. #endif
  281.  
  282. #define FIRST_OPERATOR_LINKAGE_ENTRY(scan)                \
  283.   ((char *) (((SCHEME_OBJECT *) (scan)) + FIRST_OPERATOR_LINKAGE_OFFSET))
  284.  
  285. #define NEXT_LINKAGE_OPERATOR_ENTRY(word_ptr)                \
  286.   ((char *) (((SCHEME_OBJECT *) (word_ptr)) +                \
  287.          EXECUTE_CACHE_ENTRY_SIZE))
  288.  
  289. #ifndef EXTRACT_OPERATOR_LINKAGE_ADDRESS
  290. #  define EXTRACT_OPERATOR_LINKAGE_ADDRESS(target, source)        \
  291. {                                    \
  292.   EXTRACT_EXECUTE_CACHE_ADDRESS (target, source);            \
  293. }
  294. #endif
  295.  
  296. #ifndef STORE_OPERATOR_LINKAGE_ADDRESS
  297. # define STORE_OPERATOR_LINKAGE_ADDRESS(source, target)            \
  298. {                                    \
  299.   STORE_EXECUTE_CACHE_ADDRESS (target, source);                \
  300. }
  301. #endif
  302.  
  303. /* Heuristic recovery aid. See uxtrap.c for its use.
  304.    block is the address of a vector header followed by a non-marked
  305.    header (the way that compiled blocks start).
  306.    PLAUSIBLE_CC_BLOCK_P returns true if it is likely that compiled
  307.    code is contained in the header.  This is done by checking whether
  308.    an entry is the first thing in the compiled code section.
  309.    There are two kinds of "possible entries": expressions (first thing
  310.    in the block) and procedures/continuations, which follow an interrupt
  311.    check.
  312.  */
  313.  
  314. #define PLAUSIBLE_CC_BLOCK_P(block)                    \
  315. ((PLAUSIBLE_BLOCK_START_P((block), CC_BLOCK_FIRST_ENTRY_OFFSET)) ||    \
  316.  (PLAUSIBLE_BLOCK_START_P((block),                    \
  317.               (CC_BLOCK_FIRST_ENTRY_OFFSET +        \
  318.                ENTRY_PREFIX_LENGTH))))
  319.  
  320. #define PLAUSIBLE_BLOCK_START_P(addr, offset)                \
  321. ((*((format_word *)                            \
  322.     (((char *) (addr)) + ((offset) - (sizeof (format_word)))))) ==    \
  323.    ((BYTE_OFFSET_TO_OFFSET_WORD(offset))))
  324.  
  325. #else /* not HAS_COMPILER_SUPPORT */
  326.  
  327. /* This can be anything. */
  328.  
  329. typedef unsigned short format_word;
  330.  
  331. /* Is there anything else that can be done here? */
  332.  
  333. #define GC_NO_COMPILER_STMT()                        \
  334.   gc_death                                \
  335.     (TERM_COMPILER_DEATH,                        \
  336.      "relocate_compiled: No compiler support!",                \
  337.      0, 0)
  338.  
  339. #define GC_NO_COMPILER_EXPR(value_type)                    \
  340.   ((GC_NO_COMPILER_STMT ()), (value_type 0))
  341.  
  342. #define RELOCATE_COMPILED(obj, nb, ob) (GC_NO_COMPILER_EXPR ((SCHEME_OBJECT)))
  343.  
  344. #define Transport_Compiled() (GC_NO_COMPILER_STMT ())
  345. #define Compiled_BH(flag, then_what) (GC_NO_COMPILER_STMT ())
  346. #define Get_Compiled_Block(var, address) (GC_NO_COMPILER_STMT ())
  347.  
  348. #define FIRST_MANIFEST_CLOSURE_ENTRY(scan)                \
  349.   (GC_NO_COMPILER_EXPR ((char *)))
  350.  
  351. #define MANIFEST_CLOSURE_COUNT(scan)                    \
  352.   (GC_NO_COMPILER_EXPR ((long)))
  353.  
  354. #define NEXT_MANIFEST_CLOSURE_ENTRY(word_ptr)                \
  355.   (GC_NO_COMPILER_EXPR ((char *)))
  356.  
  357. #define CLOSURE_ENTRY_END(word_ptr)                    \
  358.   (GC_NO_COMPILER_EXPR ((char *)))
  359.  
  360. #define MANIFEST_CLOSURE_END(end, start)                \
  361.   (GC_NO_COMPILER_EXPR ((SCHEME_OBJECT *)))
  362.  
  363. #define EXTRACT_CLOSURE_ENTRY_ADDRESS(target, source)            \
  364.   (GC_NO_COMPILER_STMT ())
  365.  
  366. #define STORE_CLOSURE_ENTRY_ADDRESS(source, target)            \
  367.   (GC_NO_COMPILER_STMT ())
  368.  
  369. #define READ_LINKAGE_KIND(header)                    \
  370.   (GC_NO_COMPILER_EXPR ((int)))
  371.  
  372. #define READ_CACHE_LINKAGE_COUNT(header)                \
  373.   (GC_NO_COMPILER_EXPR ((int)))
  374.  
  375. #define READ_OPERATOR_LINKAGE_COUNT(header)                \
  376.   (GC_NO_COMPILER_EXPR ((int)))
  377.  
  378. #define END_OPERATOR_LINKAGE_AREA(scan, count)                \
  379.   (GC_NO_COMPILER_EXPR ((SCHEME_OBJECT *)))
  380.  
  381. #define FIRST_OPERATOR_LINKAGE_ENTRY(scan)                \
  382.   (GC_NO_COMPILER_EXPR ((char *)))
  383.  
  384. #define NEXT_LINKAGE_OPERATOR_ENTRY(ptr)                \
  385.   (GC_NO_COMPILER_EXPR ((char *)))
  386.  
  387. #define EXTRACT_OPERATOR_LINKAGE_ADDRESS(target, source)        \
  388.   (GC_NO_COMPILER_STMT ())
  389.  
  390. #define STORE_OPERATOR_LINKAGE_ADDRESS(source, target)            \
  391.   (GC_NO_COMPILER_STMT ())
  392.  
  393. #endif /* HAS_COMPILER_SUPPORT */
  394.  
  395. #ifndef FLUSH_I_CACHE
  396. #  define FLUSH_I_CACHE() do {} while (0)
  397. #endif /* FLUSH_I_CACHE */
  398.  
  399. #ifndef COMPILER_TRANSPORT_END
  400. #  define COMPILER_TRANSPORT_END() do                    \
  401. {                                    \
  402.   Registers[REGBLOCK_CLOSURE_SPACE] = ((SCHEME_OBJECT) 0);        \
  403.   Registers[REGBLOCK_CLOSURE_FREE] = ((SCHEME_OBJECT) NULL);        \
  404.   FLUSH_I_CACHE ();                            \
  405. } while (0)
  406. #endif /* COMPILER_TRANSPORT_END */
  407.  
  408. #ifndef START_CLOSURE_RELOCATION
  409. #  define START_CLOSURE_RELOCATION(scan) do { } while (0)
  410. #endif
  411. #ifndef END_CLOSURE_RELOCATION
  412. #  define END_CLOSURE_RELOCATION(scan) do { } while (0)
  413. #endif
  414.  
  415. #ifndef START_OPERATOR_RELOCATION
  416. #  define START_OPERATOR_RELOCATION(scan) do { } while (0)
  417. #endif
  418. #ifndef END_OPERATOR_RELOCATION
  419. #  define END_OPERATOR_RELOCATION(scan) do { } while (0)
  420. #endif
  421.  
  422. #endif /* CMPGC_H_INCLUDED */
  423.